home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Id: scratch.c,v 0.91 1994/02/20 00:52:51 zhao Pre-Release $
- *
- *. This file is part of BIT shareware package. After the two weeks of
- * free evaluation period, you are encouraged (required) to register
- * your copy for a small registration fee, which is $35 for personal use
- * and $50 for commercial, government and institutional use.
- *
- * Copyright(c) 1993, 1994 by T.C. Zhao.
- * All rights reserved.
- *
- * Permission to use, copy, and distribute this software in its entirety
- * for non-commercial purposes is hereby granted, provided that the
- * above shareware and copyright notices and this permission notice
- * appear in all copies and their documentation.
- *
- * This software may be modified for your own use, but modified versions
- * may not be distributed without prior consent of the author.
- *
- * This software is provided "as is" without expressed or implied
- * warranty of any kind.
- *
- *.
- *
- * A. Scratch files for possible backing store. Neither portable nor
- * efficient. Probably should make it portable.
- *
- * B. Hacks to read compressed and not-directly-supported formats
- *
- */
- #if !defined(lint) && defined(F_ID)
- char *id_sh = "$Id: scratch.c,v 0.91 1994/02/20 00:52:51 zhao Pre-Release $";
- #endif
-
- #include "bit.h"
- #include "dmalloc.h"
-
- /******************************************************************
- * Handle TMP file formats
- *
- * For the specification of the BIT1.0 format, See files in ../docs
- * directory.
- **************************************************************{*/
-
- /************************* Limits and defines ********************/
-
- #define TMPSIG "BIT1.0" /* signature */
- #define TMPSIGL (sizeof(TMPSIG)-1) /* its length */
-
- /*********************** Local variables ************************/
-
- static int pc_resolution, channel, compression;
-
- /**************************************************************/
- int
- TMP_desc(IPTR im)
- {
- char buf[10];
- FILE *fp = im->fp;
-
- fread(buf, 1, TMPSIGL, fp); /* ignore signature */
-
- im->w = get2LSBF(fp);
- im->h = get2LSBF(fp);
- pc_resolution = getc(fp);
- channel = getc(fp);
- compression = getc(fp);
-
- M_info("TMP_desc", "%s: Res=%d Channel=%d Comp=%d",
- pc_resolution, channel, compression);
-
- if (pc_resolution < 0 || pc_resolution > 2)
- {
- Bark("TMP_desc", "Bad PC resolution: %d", pc_resolution);
- return -1;
- }
-
- if (channel < 0)
- {
- Bark("TMP_desc", "Bad color components: %d", channel);
- return -1;
- }
-
- if (channel > 4 && !(channel == 5 && pc_resolution == 1))
- {
- Bark("TMP_desc", "Bad color components: %d", channel);
- return -1;
- }
-
- if (channel == 0 || channel == 2)
- { /* colormap */
- int ncolors = get2LSBF(fp);
- if (ncolors < 0)
- {
- Bark("TMP_desc", "Bad colormap entries: %d", ncolors);
- return -1;
- }
- im->colors = im->cmap->colors = ncolors;
- if (pc_resolution == sizeof(pc_t))
- {
- fread(im->cmap->ct[0], sizeof(pc_t), ncolors, fp);
- fread(im->cmap->ct[1], sizeof(pc_t), ncolors, fp);
- fread(im->cmap->ct[2], sizeof(pc_t), ncolors, fp);
- }
- else
- { /* to be implemented */
- Bark("TMP_desc", "highier resolution not supported yet");
- return -1;
- }
- im->type = channel ? T_GMAP : T_CMAP;
- }
- else
- { /* truecolor */
- im->type = channel == 1 ? T_GRAY : T_RGBA;
- }
- return 0;
- }
-
- /*****************************************************************/
-
- int
- TMP_load(IPTR im)
- {
- FILE *fp = im->fp;
- size_t total = im->w * im->h;
- long ok = total;
-
- show_busy("Loading ...");
- im->xi = get2LSBF(fp);
- im->yi = get2LSBF(fp);
- im->xf = im->xi + im->w - 1;
- im->yf = im->yi + im->h - 1;
-
- if (compression)
- {
- to_be_written("TMP_load compression");
- return -1;
- }
- if (IS_CI(im))
- { /* colormap */
- ok = fread(im->raster, im->esize, total, fp);
- }
- else if (channel != 5)
- { /* non-packed */
- int r, g, b, a;
- rgba_t *ras = im->raster, *rs;
-
- /* if we get here, we know resolution must be 1 */
-
- #if 0 /* forcing use getc */
- int (*readit) (FILE *);
- readit = (resolution == 1) ? fgetc : get2LSBF;
- #else
-
- #define readit getc
- #endif
-
-
- if (channel == 1)
- {
- for (rs = ras + total; ras < rs; ras++)
- {
- r = readit(fp);
- *ras = Pack(r, r, r);
- }
- }
- else if (channel == 3)
- {
- for (rs = ras + total; ras < rs; ras++)
- {
- r = readit(fp);
- g = readit(fp);
- b = readit(fp);
- *ras = Pack(r, g, b);
- }
- }
- else if (channel == 4)
- {
- for (rs = ras + total; ras < rs; ras++)
- {
- r = readit(fp);
- g = readit(fp);
- b = readit(fp);
- a = readit(fp);
- *ras = Pack4(r, g, b, a);
- }
- }
- }
- else
- { /* packed already */
- ok = fread(im->raster, sizeof(rgba_t), total, fp);
- }
- end_busy();
- return (ok > total / 2) ? im->h : -1;
- }
-
- /***************** Writing Routines *****************************/
- static int packedpix = 1;
-
- /* ARGSUSED */
- const char *
- TMP_wdefault(const IPTR im)
- {
- return packedpix ? "Packed" : "Non-packed";
- }
-
- /* ARGSUSED */
- int
- TMPdump_init(IPTR im)
- {
- return (packedpix = !packedpix);
- }
-
- int
- TMP_dump(IPTR im)
- {
- size_t total = im->w * im->h;
- FILE *fp = im->fp;
-
- show_busy("Writing ...");
-
- if (Badfwrite(TMPSIG, 1, TMPSIGL, fp))
- return -1;
-
- put2LSBF(im->w, fp);
- put2LSBF(im->h, fp);
- putc(sizeof(pc_t), fp);
-
- /* always write channel 5 */
- channel = IS_CI(im) ? (IS_GRAY(im) ? 2 : 0) :
- (IS_GRAY(im) ? 1 : (packedpix ? 5 : 3));
-
- putc(channel, fp);
- putc(0, fp); /* compression */
-
-
- if (IS_CI(im))
- {
- int ncolors = im->cmap->colors;
- put2LSBF(ncolors, fp);
- fwrite(im->cmap->ct[0], 1, ncolors, fp);
- fwrite(im->cmap->ct[1], 1, ncolors, fp);
- fwrite(im->cmap->ct[2], 1, ncolors, fp);
- }
- put2LSBF(im->xi, fp);
- put2LSBF(im->yi, fp);
-
- if (IS_CI(im))
- {
- fwrite(im->raster, sizeof(ci_t), im->w * im->h, fp);
- }
- else if (channel == 1)
- { /* grayscale */
- register rgba_t *ras = im->raster, *rs;
- for (rs = ras + total; ras < rs; ras++)
- {
- putc((*ras & 0xff), fp);
- }
- }
- else if (channel == 3)
- { /* seperate RGB */
- register rgba_t *ras = im->raster, *rs;
- register int r, g, b;
- for (rs = ras + total; ras < rs; ras++)
- {
- Unpack(*ras, r, g, b);
- putc(r, fp);
- putc(g, fp);
- putc(b, fp);
- }
- }
- else
- {
- fwrite(im->raster, sizeof(rgba_t), total, fp);
- }
- end_busy();
- return fflush(fp);
- }
-
- /***********************************************************************
- * END OF TMP FILE
- ******************************************************************}*/
-
-
- /**************************************************************************
- *
- * FORMATS that rely on external program to convert to one of the known
- * formats. Can't use popen(.....) because we need to guarantee seek-ability
- *
- **************************************************************************/
-
- #include <stdlib.h> /* for system */
- static const char *pref = ".BIT"; /* tmp file prefix */
- extern IMG_IO img_io[];
-
- /********************************************************************
- * the driver routine that uncompress/converts or whatever to read
- * an images description. It takes command names, options and whole
- * bunch of things to do the magic
- ********************************************************************/
- static int
- fake_desc(IPTR im, const char *cmds[], const char *func, const char *prgs)
- {
- char cmd[1024];
- const char *const *q = cmds;
- int found[5], i, status, total;
- char *tmp_file;
- IMG_IO *p;
- FILE *fp;
-
- /* get a tmp file to hold the output */
- if (!(tmp_file = get_tmpf(pref)))
- {
- Bark(func, "Unable to get tmpfile");
- return -1;
- }
-
- update_filename(im->ifile);
- update_format_info(im);
-
- /* now try all given conversion commands. */
- show_busy(prgs);
- do
- {
- sprintf(cmd, *q, im->ifile, tmp_file);
- status = system(cmd);
- }
- while (status && *++q);
- end_busy();
-
- if (status) /* did not succeed */
- {
- Bark(func, "Bad command");
- del_tmpf(tmp_file);
- return -1;
- }
-
- /*
- * conversion is successful. Try to read it. Can't simply use open_image
- * to do it because of bad recursion would occur
- */
- if (!(fp = fopen(tmp_file, "r")))
- {
- del_tmpf(tmp_file);
- return -1;
- }
-
- /* see if processed file is one of the formats we can handle */
- if ((total = check_signature(fp, found, tmp_file)) <= 0)
- {
- del_tmpf(tmp_file);
- return -1;
- }
-
- /*
- * so far so good. Do all signature matches until we get a good
- * description. However, before we hand over the stuff to get_desc, need
- * to change the filename to the real file because canned library might
- * ignore im->fp and want to open file and do its things ...
- */
-
- strcpy(cmd, im->ifile);
- strcpy(im->ifile, tmp_file);
- im->fp = fp;
-
- i = 0;
- do
- {
- rewind(im->fp);
- im->io = (p = img_io + found[i]);
- im->t2b = p->t2b;
- im->type = p->type;
- if (!im->io->display)
- im->io->display = Generic_display;
- status = im->io->desc(im);
- }
- while (++i < total && status < 0);
-
- /* now we can safely delete the file regardless status */
- del_tmpf(tmp_file);
-
- strcpy(im->ifile, cmd);
- update_filename(im->ifile);
- return status;
- }
-
- /**********************************************************************
- * The writing routine. All depends on structure FakeDump. The format
- * string should be a command name, and four string producers to accept
- * option, infile, outfile and option2, e.g., "pnmtotiff %s %s > %s %s" is
- * an acceptable one.
- **********************************************************************/
- typedef struct
- {
- const char *cmd; /* shell command to do it */
- char *keys[4]; /* formats cmd accepts */
- int optlast; /* for totiff. Weird stuff */
- }
- FakeDump;
-
- /**********************************************************
- * The driver
- *********************************************************/
- static int
- fake_dump(IPTR im, FakeDump * fake, const char *opt1, const char *opt2,
- const char *func, const char *prgs)
- {
- int in, err;
- FakeDump *f = fake;
- char cmd[MAXDLEN + MAXFLEN], sf[MAXDLEN + MAXFLEN];
- char *tmpf;
- const char *o1 = opt1 ? opt1 : "", *o2 = opt2 ? opt2 : "";
-
-
- if (!(tmpf = get_tmpf(pref)))
- {
- Bark(func, "Unable to get tmpfile");
- return -1;
- }
-
- /*
- * again, need to save filenames. Some formats do its own things with
- * file names ....
- */
-
- strcpy(sf, im->ofile);
- strcpy(im->ofile, tmpf);
- do
- {
- /*
- * if the writing routine takes multiple formats, always choose the
- * format that is closest to current image
- */
-
- err = (in = best_format(im, f->keys)) < 0;
-
- /*
- * if the format needed and the best format is not the same,
- * convert to needed
- */
-
- err = err || (img_io[in].type != T_FLEX &&
- img_io[in].type != im->type &&
- img_convert_type(im, img_io[in].type));
-
- /* write current image to disk in proper format */
- err = err || !(im->fp = fopen(tmpf, "w"));
- err = err || (img_io[in].dump(im) < 0);
- close_image(im);
-
- /* generate the necassary shell command to do the job */
-
- if (f->optlast)
- sprintf(cmd, f->cmd, "", tmpf, sf, o2);
- else
- sprintf(cmd, f->cmd, o1, tmpf, sf, "");
-
- /* do it */
- M_info("Executing", cmd);
- show_busy(prgs);
- err = err || system(cmd);
- }
- while (++f && f->cmd && err);
- del_tmpf(tmpf);
- strcpy(im->ofile, sf);
- end_busy();
- return err;
- }
-
- /****************************************************************
- * Compressed file hack. No much to do
- ****************************************************************/
- #ifndef NO_COMPRESS
- int
- Compress_desc(IPTR im)
- {
- static const char *cmds[] =
- {
- "zcat %s > %s", 0
- };
- int status;
- static char newinfo[128];
-
- strcpy(newinfo, im->io->info);
- status = fake_desc(im, cmds, "CompressDesc", "Uncompressing ...");
- strcat(newinfo, im->io->key);
- im->info = newinfo;
- return status;
- }
-
- /***************************************************************
- * after description, flow should've been directed to the true
- * format reader via io->load, should not be here. If it reaches,
- * something is very wrong
- **************************************************************/
- /* ARGSUSED */
- int
- Compress_load(IPTR im)
- {
- Bark("CompressLoad", "Should be be here");
- return -1;
- }
- #endif /* !NO_COMPRESS */
-
- /****************************************************************
- * TIFF file support hack. Someday, I will make tiff a first
- * class citizen.
- *****************************************************************/
- #ifndef NO_TIFF
-
- /************************************************************
- * The description routine. Again, no much to do, just call
- * call fake_desc and done with it
- ***********************************************************/
- int
- TIFF_desc(IPTR im)
- {
- static const char *cmds[] =
- {
- "fromtiff %s %s",
- "tifftopnm %s > %s",
- 0
- };
- int status;
- const char *oldkey = im->io->key, *oldinfo = im->io->info;
-
- /*
- * must save old io->key and io->info because fake_desc will replace this
- * with whatever it read, e.g., IRIS RGB, we certainly don't want to
- * reading a tiff file while reporting we have read an IRIS RGB
- */
-
- status = fake_desc(im, cmds, "TIFF_Desc", "Reading ...");
-
- /* cheat again to get the reporting right. Two wrongs make a right! */
- im->key = oldkey;
- im->info = oldinfo;
- return status;
- }
-
- /***************************************************************
- * After description, flow should've been directed to the
- * true loader via io->load. Should not be here
- ***************************************************************/
- /* ARGSUSED */
- int
- TIFF_load(IPTR im)
- {
- Bark("TIFF_Load", "Should be be here");
- return -1;
- }
-
- static int tifflzw;
- /* ARGSUSED */
- int
- TIFF_dumpinit(IPTR im)
- {
- tifflzw = !tifflzw;
- return 0;
- }
-
- /* ARGSUSED */
- const char *
- TIFF_wdefault(const IPTR im)
- {
- return tifflzw ? "Compress" : "No Compress";
- }
-
- /*********************************************************
- * write a tiff file either thru totiff or pnmtotiff
- *********************************************************/
- int
- TIFF_dump(IPTR im)
- {
- static FakeDump tiffdump[] =
- {
- /* totiff routiens */
- {"totiff %s %s %s %s", /* command line */
- {"iris", 0}, /* accepted formtats */
- 1 /* if option goes last (wierd) */
- },
-
- /* PBMPlus routines */
- {"pnmtotiff %s %s > %s %s",
- {"ppm", "pgm", "pbm", 0},
- 0
- },
-
- /* sentinel */
- {0}
- };
-
- return fake_dump(im, tiffdump, tifflzw ? "-lzw" : "-none",
- tifflzw ? "-c" : 0, "TIFFDump", "PleaseWait ...");
- }
-
- #endif /* ! NO_TIFF */
-
- /** routines for developing bit *********/
-
- #ifdef DEVELOP_BIT
-
- /***************************************************************
- * Generate a GL cursor bitmap (16x16 mono only)
- ***************************************************************/
- int
- CUR_dump(IPTR im)
- {
- unsigned short ch[17];
- unsigned short *cur = ch;
- bw_t *bw;
- char vname[512], *t;
- FILE *fp = im->fp;
- int i, j, k;
-
- if (im->w != 16 || im->h != 16)
- {
- Bark("GLCurDef", "Bad bitmap");
- return -1;
- }
-
- strcpy(vname, im->ofile);
-
- /* zap the extension if any */
- if ((t = strchr(vname, '.')))
- *t = '\0';
-
- for (i = 0; i < im->h; i++)
- {
- bw = ((bw_t **) im->mraster)[i];
- for (*cur = 0, j = 0, k = 15; j < 16; j++, k--, bw++)
- *cur |= (*bw != 0) << k;
- cur++;
- }
-
- /** write it */
- fprintf(fp, "static unsigned short %s[] =\n {", vname); /* } VI */
- for (cur = ch, i = 0; i < 16; i += 8)
- {
- fprintf(fp, "%c\n 0x%04x, ", i == 0 ? ' ' : ',', *cur++);
- fprintf(fp, "0x%04x, ", *cur++);
- fprintf(fp, "0x%04x, ", *cur++);
- fprintf(fp, "0x%04x, ", *cur++);
- fprintf(fp, "0x%04x, ", *cur++);
- fprintf(fp, "0x%04x, ", *cur++);
- fprintf(fp, "0x%04x, ", *cur++);
- fprintf(fp, "0x%04x", *cur++);
- } /* { *VI */
-
- fputs("\n };\n", fp);
- return fflush(fp);
- }
-
- int
- CUR_desc(IPTR im)
- {
- return -1;
- }
-
- /*******************************************************************
- * Write GL Patterns from a bitmap. Pattern is 32x32 bits packed
- * into 2 * 32 shorts
- *******************************************************************/
- int
- PAT_dump(IPTR im)
- {
- unsigned short ph[65], *pat;
- bw_t *bw;
- FILE *fp = im->fp;
- int i, j, k;
- char vname[512], *t;
-
- if (im->w != 32 || im->h != 32)
- {
- Bark("GLPatternWrite", "Bad input bitmap");
- return -1;
- }
-
- strcpy(vname, im->ofile);
-
- /* zap the extension if any */
- if ((t = strchr(vname, '.')))
- *t = '\0';
-
- pat = ph;
- /* covert to GL patterns */
- for (j = 0; j < im->h; j++)
- {
- bw = ((bw_t **) im->mraster)[j];
-
- for (*pat = 0, k = 15, i = 0; i < 16; k--, i++, bw++)
- *pat |= (*bw != 0) << k;
- pat++;
-
- for (*pat = 0, k = 15, i = 0; i < 16; k--, i++, bw++)
- *pat |= (*bw != 0) << k;
- pat++;
- }
-
- /** write it */
- fprintf(fp, "static unsigned short %s[] =\n {", vname); /* } VI */
- for (pat = ph, i = 0; i < 64; i += 8)
- {
- fprintf(fp, "%c\n 0x%04x, ", i == 0 ? ' ' : ',', *pat++);
- fprintf(fp, "0x%04x, ", *pat++);
- fprintf(fp, "0x%04x, ", *pat++);
- fprintf(fp, "0x%04x, ", *pat++);
- fprintf(fp, "0x%04x, ", *pat++);
- fprintf(fp, "0x%04x, ", *pat++);
- fprintf(fp, "0x%04x, ", *pat++);
- fprintf(fp, "0x%04x", *pat++);
- } /* { *VI */
-
- fputs("\n };\n", fp);
- return fflush(fp);
- }
-
- int
- PAT_desc(IPTR im)
- {
- return -1;
- }
-
- #endif /* DEVELOP */
-